
#ifndef _TTG_STRUCTURES_ENUMERATORS_
#define _TTG_STRUCTURES_ENUMERATORS_
#include "Common/Definitions.h"

#include <list>
#include <vector>

namespace ttg
{
	namespace structures
	{
		//Represents collection, which can be observed.
		template <class T>
		class Enumerator
		{
			public:
				//Moves to next element. If there aren't any, returns false.
				virtual bool moveNext() = 0;
				//Returns current element.
				virtual T &current() = 0;
				//Resets enumerator to initial state.
				virtual void reset() = 0;
				//Builds std::vector<T> according to Enumerator.
				virtual std::vector<T> buildVector()
				{
					std::vector<T> res;
					while (moveNext())
						res.push_back(current());
					return res;
				}
				//Builds std::list<T> according to Enumerator.
				virtual std::list<T> buildList()
				{
					std::list<T> res;
					while (moveNext())
						res.push_back(current());
					return res;
				}
				//For descendants only.
				virtual ~Enumerator()
				{ /*nothing*/ }
		};

		//Wrapps arbitrary stl iterator (from list, vector, etc).
		//Note: "Iter" must support operator ++(int);
		template <class T, class Iter>
		class StlEnumerator :public Enumerator<T>
		{
			private:
				Iter begin;
				Iter cur;
				Iter end;
				bool isfirstcall;
			public:
				//Creates enumerator for elements, which is belongs to [begin, end).
				inline StlEnumerator(Iter begin, Iter end)
				{
					this->cur = this->begin = begin;
					this->end = end;
					this->isfirstcall = true;
				}
				//Moves to next element. If there aren't any, returns false.
				virtual bool moveNext()
				{
					if (isfirstcall)
					{
						isfirstcall = false;
						return begin != end;
					}
					else
					{
						if (cur != end)
							cur++;
						return cur != end;
					}
				}
				//Returns current element.
				virtual T &current()
				{
					return *cur;
				}
				//Resets enumerator to initial state.
				virtual void reset()
				{
					cur = begin;
					isfirstcall = true;
				}
		};

		//Wraps single value into Enumerator.
		//May be usefull for higher code reusage.
		template <class T>
		class ValueEnumerator :public Enumerator<T>
		{
			private:
				T val;
				bool is_first;
			public:
				//Wraps given value as enumerator.
				ValueEnumerator(T value)
					:val(value)
				{
					this->is_first = true;
				}
				//Moves to next element. If there aren't any, returns false.
				virtual bool moveNext()
				{
					bool res = is_first;
					is_first = false;
					return res;
				}
				//Returns current element.
				virtual T &current()
				{
					return val;
				}
				//Resets enumerator to initial state.
				virtual void reset()
				{
					is_first = true;
				}
		};
	}
}

#endif
